package app

import (
	"common/logging"
	"encoding/json"
	"errors"

	"iot/iot_app_server/app/util"
	"iot/iot_app_server/app/device"
	"iot/iot_app_server/proto"

	"github.com/golang/protobuf/proto"
)

//启动时注册，只读不写，不用加锁
var (
	HandleMap     = make(map[string]util.UpMsgHandle)
	AsynHandleMap = make(map[string]bool)
)

//启动时注册，不支持动态添加
func registerMsgHandle() {

	// scene
	//HandleMap["/scene/list"] = scene.HandleListScene_DEVICE
	HandleMap["usr.report"] = device.HandleReportGW
	HandleMap["usr.d2t"] = device.HandleD2tGW

}

func registerAsynMsgHandle() {
	AsynHandleMap["/update_zb_ack/"] = true
	AsynHandleMap["/w_zb_ack/"] = true
	AsynHandleMap["/upd_all_zb_ack/"] = true
	AsynHandleMap["/get_gw_status_ack/"] = true

	//subdevice
	AsynHandleMap["/subdevice/add/ack"] = true
	AsynHandleMap["/subdevice/del/ack"] = true //都添加一下
	AsynHandleMap["/subdevice/set_alarm_device/ack"] = true
	//Infrared subdevice
	AsynHandleMap["/subdevice/infrared/order/clean/ack"] = true
	AsynHandleMap["/subdevice/infrared/order/del/ack"] = true

	//lock device
	AsynHandleMap["/subdevice/unlock/generate/ack"] = true

	// transport
	AsynHandleMap["/transport/ack"] = true
	AsynHandleMap["usr.ctl_ack"] = true
	AsynHandleMap["/debug/ack"] = true
	AsynHandleMap["usr.ctl.led_ack"] = true

	// scene
	AsynHandleMap["/scene/add/ack"] = true
	AsynHandleMap["/scene/del/ack"] = true
	AsynHandleMap["/scene/update/ack"] = true
	AsynHandleMap["/scene/enable/ack"] = true
	//update
	AsynHandleMap["/ota/update/check/ack"] = true

	AsynHandleMap["/ota_get_progress_ack/"] = true
	AsynHandleMap["/ota_start_update_ack/"] = true
	AsynHandleMap["/alarm/release/ack"] = true

	// defence
	AsynHandleMap["/defence/add/ack"] = true
	AsynHandleMap["/defence/delete/ack"] = true
	AsynHandleMap["/defence/update/ack"] = true
	AsynHandleMap["/defence/switch/ack"] = true
}

func init() {
	registerMsgHandle()
	registerAsynMsgHandle()
}

type PayloadInfo struct {
	Msgid string
	Data  interface{}
}

//每个消息都会起一个协程来调用dispatcher函数,所以dispatcher函数里可以阻塞,不影响其他消息的处理
func UpstreamDispatcher(data []byte) error {
	//logging.Info("UpstreamDispatcher data:%+v", string(data))
	//unmarshal
	reqPub := &MSGBUS_DOWNSTREAM.MqttPub{}
	err := proto.Unmarshal(data, reqPub)
	if err != nil {
		logging.Error("UpstreamDispatcher Unmarshal MqttPub failed")
		return err
	}
	logging.Info("UpstreamDispatcher reqPub=%+v", reqPub)
	topic := reqPub.GetTopic()
	/*
		topic := reqPub.GetTopic()
		pos := strings.LastIndex(topic, "/")
		if pos == -1 {
			logging.Error("UpstreamDispatcher invalid topic:%s", reqPub.Topic)
			return errors.New("invalid topic")
		}

		topicPrefix := topic[0 : pos+1]
		topicPara := topic[pos+1 : len(topic)]
	*/

	logging.Debug("UpstreamDispatcher topic=%s", topic)

	//异步handle
	if AsynHandleMap[topic] {
		payload := &PayloadInfo{}
		err := json.Unmarshal(reqPub.Msg, payload)
		logging.Info("UpstreamDispatcher AsynHandleMap Unmarshal payload=%+v", payload)
		if err != nil || payload.Msgid == "" {
			logging.Error("UpstreamDispatcher asyn handle invalid payload, payload=%s,err=%s", string(reqPub.Msg), err)
			return nil
		}

		msgItem := util.MsgManagerInstance.GetMsg(string(payload.Msgid))
		logging.Info("UpstreamDispatcher msgItem=%+v", msgItem)
		if msgItem != nil {
			select {
			case msgItem.MsgChan <- reqPub:
				break
			default:
				//这种场景是概率非常小的，就是此时刚好超时
				logging.Error("UpstreamDispatcher asyn handle  exactly time out,reqPub=%+v", reqPub)
			}
		} else {
			logging.Info("UpstreamDispatcher asyn handle  ,msg not exist,maybe timeout,reqPub=%+v", reqPub)
		}
		return nil
	}

	handleFunc := HandleMap[topic]
	if handleFunc == nil {
		logging.Error("UpstreamDispatcher invalid topic,topic=%s,reqPub=%+v", topic, reqPub)
		return errors.New("invalid topic")
	}
	handleFunc(reqPub, nil)
	return nil
}
